package com.itheima.prize.msg;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.prize.commons.config.RedisKeys;
import com.itheima.prize.commons.db.entity.CardGame;
import com.itheima.prize.commons.db.entity.CardGameProduct;
import com.itheima.prize.commons.db.entity.CardGameRules;
import com.itheima.prize.commons.db.entity.CardProduct;
import com.itheima.prize.commons.db.service.*;
import com.itheima.prize.commons.utils.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * 活动信息预热，每隔1分钟执行一次
 * 查找未来1分钟内（含），要开始的活动
 */
@Component
public class GameTask {
    private final static Logger log = LoggerFactory.getLogger(GameTask.class);
    @Autowired
    private CardGameService gameService;
    @Autowired
    private CardGameProductService cardGameProductService;
    @Autowired
    private CardGameRulesService gameRulesService;
    @Autowired
    private GameLoadService gameLoadService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CardProductService cardProductService;

    @Scheduled(cron = "0 * * * * ?")
    public void execute() {
        System.out.printf("scheduled!" + new Date());
        //TODO：任务5.1-缓存预热-调度写入缓存

        //1.扫描表
        //当前时间
        // 定义HKT时区
        ZoneId hktZone = ZoneId.of("Asia/Hong_Kong");
        // 获取系统当前时间，并转换到HKT时区
        ZonedDateTime now = ZonedDateTime.now(hktZone);
        // 转换为时间戳（秒）
        long nowTime = now.toInstant().getEpochSecond();
        // 计算当前时间加 60 秒的时间
        ZonedDateTime nowPlus60 = now.plus(60, ChronoUnit.SECONDS);

        // 构建查询条件
        QueryWrapper<CardGame> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("starttime", now)
                .le("starttime", nowPlus60);
        List<CardGame> gameList = gameService.list(queryWrapper);


        if (gameList.isEmpty()) {
            log.info("没有查询到活动");
        } else {
            //2.查到数据存入数据（活动信息，活动规则，活动数量，奖品信息）
            log.info("查询到的活动" );

            Date starttime ;
            Date endtime ;
            long startTime;
            long endTime;

            for (CardGame game : gameList) {
                //1.存入活动信息
                log.info("正在存入活动信息");
                redisUtil.set(RedisKeys.INFO + game.getId(), game, -1);

                starttime = game.getStarttime();
                endtime = game.getEndtime();
                startTime = starttime.getTime();
                endTime = endtime.getTime();

                //2.查询活动相关规则存入缓存
                QueryWrapper<CardGameRules> query = new QueryWrapper<>();
                //gameId
                Integer gameId = game.getId();
                query.eq("gameid", gameId);
                List<CardGameRules> gameRules = gameRulesService.list(query);

                log.info("正在存入活动规则");
                //遍历规则，分别存入最大中奖数、可抽奖次数，概率
                for (CardGameRules r : gameRules) {
                    //可抽奖次数
                    redisUtil.hset(RedisKeys.MAXENTER + gameId, r.getUserlevel() + "", r.getEnterTimes(), endTime+86400);
                    //最大中奖数
                    redisUtil.hset(RedisKeys.MAXGOAL + gameId, r.getUserlevel() + "", r.getGoalTimes(),endTime+86400 );
                    //中奖概率
                    redisUtil.hset(RedisKeys.RANDOMRATE + gameId, r.getUserlevel() + "", r.getRandomRate(), endTime+86400);
                }


                //统计总数量
                int amount = 0;

                //3.获取奖品列表
                QueryWrapper<CardGameProduct> queryGameProduct = new QueryWrapper<>();
                queryGameProduct.eq("gameid", gameId);
                List<CardGameProduct> productInfo = cardGameProductService.list(queryGameProduct);

                for (CardGameProduct cardGameProduct : productInfo) {
                    amount += cardGameProduct.getAmount();
                }


                List<Long> tokenList = new ArrayList<>();
               long rnd = endTime -startTime;
                //有多少奖品生成多少时间戳
                for (int i = 0; i < amount; i++) {
                    tokenList.add(rnd *1000+ new Random().nextInt(999));
                }


                //创建一个奖品列表 存放每一个奖品列表  存放对应数量的奖品信息
                List<CardProduct> cardProductList = new ArrayList<>();
                for (CardGameProduct cardGameProduct : productInfo) {
                    int number = cardGameProduct.getAmount();
                    for (int i = 0; i < number; i++) {
                        cardProductList.add(cardProductService.getById(cardGameProduct.getProductid()));
                    }
                }

                //4.为奖品与令牌创建联系
                //过期时间
                Long expire = endTime - nowTime;
                log.info("正在存入奖品映射");
                //存入奖品映射设置过期时间
                for (int i = 0; i < tokenList.size(); i++) {
                    redisUtil.set(RedisKeys.TOKEN + gameId + "_" + tokenList.get(i), cardProductList.get(i), expire);
                }

                //存入令牌桶 设置有效期
                log.info("正在存入令牌桶");
                tokenList.sort(Long::compareTo);
                redisUtil.rightPushAll(RedisKeys.TOKENS + gameId, tokenList);
                redisUtil.expire(RedisKeys.TOKENS + gameId, expire);

            }
        }


    }
}
